//===--- CGFloat.swift.gyb ------------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

%{

from SwiftIntTypes import all_integer_types

# Number of bits in the Builtin.Word type
word_bits = int(CMAKE_SIZEOF_VOID_P) * 8

}%

@_exported import CoreGraphics
import Darwin

@frozen
public struct CGFloat {
#if arch(i386) || arch(arm)
  /// The native type used to store the CGFloat, which is Float on
  /// 32-bit architectures and Double on 64-bit architectures.
  public typealias NativeType = Float
#elseif arch(x86_64) || arch(arm64)
  /// The native type used to store the CGFloat, which is Float on
  /// 32-bit architectures and Double on 64-bit architectures.
  public typealias NativeType = Double
#endif

  @_transparent public init() {
    self.native = 0.0
  }

  @_transparent public init(_ value: Float) {
    self.native = NativeType(value)
  }

  @_transparent public init(_ value: Double) {
    self.native = NativeType(value)
  }

#if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64))
  @_transparent public init(_ value: Float80) {
    self.native = NativeType(value)
  }
#endif

  @_transparent public init(_ value: CGFloat) {
    self.native = value.native
  }

  /// The native value.
  public var native: NativeType
}

extension CGFloat : SignedNumeric {
  @_alwaysEmitIntoClient // availability
  public init<T: BinaryInteger>(_ source: T) {
    self.native = NativeType(source)
  }

  @_transparent
  public init?<T: BinaryInteger>(exactly source: T) {
    guard let native = NativeType(exactly: source) else { return nil }
    self.native = native
  }

  @_transparent
  public var magnitude: CGFloat {
    return CGFloat(native.magnitude)
  }
}

extension CGFloat : BinaryFloatingPoint {

  public typealias RawSignificand = UInt
  public typealias Exponent = Int

  @_transparent
  public static var exponentBitCount: Int {
    return NativeType.exponentBitCount
  }

  @_transparent
  public static var significandBitCount: Int {
    return NativeType.significandBitCount
  }

  //  Conversions to/from integer encoding.  These are not part of the
  //  BinaryFloatingPoint prototype because there's no guarantee that an
  //  integer type of the same size actually exists (e.g. Float80).
  @_transparent
  public var bitPattern: UInt {
    return UInt(native.bitPattern)
  }

  @_transparent
  public init(bitPattern: UInt) {
    native = NativeType(bitPattern: UInt${word_bits}(bitPattern))
  }

  @_transparent
  public var sign: FloatingPointSign {
    return native.sign
  }

  @_transparent
  public var exponentBitPattern: UInt {
    return native.exponentBitPattern
  }

  @_transparent
  public var significandBitPattern: UInt {
    return UInt(native.significandBitPattern)
  }

  @_transparent
  public init(sign: FloatingPointSign,
              exponentBitPattern: UInt,
              significandBitPattern: UInt) {
    native = NativeType(sign: sign,
      exponentBitPattern: exponentBitPattern,
      significandBitPattern: NativeType.RawSignificand(significandBitPattern))
  }

  @_transparent
  public init(nan payload: RawSignificand, signaling: Bool) {
    native = NativeType(nan: NativeType.RawSignificand(payload),
                        signaling: signaling)
  }

  @_transparent
  public static var infinity: CGFloat {
    return CGFloat(NativeType.infinity)
  }

  @_transparent
  public static var nan: CGFloat {
    return CGFloat(NativeType.nan)
  }

  @_transparent
  public static var signalingNaN: CGFloat {
    return CGFloat(NativeType.signalingNaN)
  }

  @available(*, unavailable, renamed: "nan")
  public static var quietNaN: CGFloat {
    fatalError("unavailable")
  }

  @_transparent
  public static var greatestFiniteMagnitude: CGFloat {
    return CGFloat(NativeType.greatestFiniteMagnitude)
  }

  @_transparent
  public static var pi: CGFloat {
    return CGFloat(NativeType.pi)
  }

  @_transparent
  public var ulp: CGFloat {
    return CGFloat(native.ulp)
  }

  @_transparent
  public static var leastNormalMagnitude: CGFloat {
    return CGFloat(NativeType.leastNormalMagnitude)
  }

  @_transparent
  public static var leastNonzeroMagnitude: CGFloat {
    return CGFloat(NativeType.leastNonzeroMagnitude)
  }

  @_transparent
  public var exponent: Int {
    return native.exponent
  }

  @_transparent
  public var significand: CGFloat {
    return CGFloat(native.significand)
  }

  @_transparent
  public init(sign: FloatingPointSign, exponent: Int, significand: CGFloat) {
    native = NativeType(sign: sign,
      exponent: exponent, significand: significand.native)
  }

  @_transparent
  public mutating func round(_ rule: FloatingPointRoundingRule) {
    native.round(rule)
  }

  @_transparent
  public var nextUp: CGFloat {
    return CGFloat(native.nextUp)
  }

  @_transparent
  public mutating func negate() {
    native.negate()
  }

  @_transparent
  public static func +=(lhs: inout CGFloat, rhs: CGFloat) {
    lhs.native += rhs.native
  }

  @_transparent
  public static func -=(lhs: inout CGFloat, rhs: CGFloat) {
    lhs.native -= rhs.native
  }

  @_transparent
  public static func *=(lhs: inout CGFloat, rhs: CGFloat) {
    lhs.native *= rhs.native
  }

  @_transparent
  public static func /=(lhs: inout CGFloat, rhs: CGFloat) {
    lhs.native /= rhs.native
  }

  @_transparent
  public mutating func formTruncatingRemainder(dividingBy other: CGFloat) {
    native.formTruncatingRemainder(dividingBy: other.native)
  }

  @_transparent
  public mutating func formRemainder(dividingBy other: CGFloat) {
    native.formRemainder(dividingBy: other.native)
  }

  @_transparent
  public mutating func formSquareRoot( ) {
    native.formSquareRoot( )
  }

  @_transparent
  public mutating func addProduct(_ lhs: CGFloat, _ rhs: CGFloat) {
    native.addProduct(lhs.native, rhs.native)
  }

  @_transparent
  public func isEqual(to other: CGFloat) -> Bool {
    return self.native.isEqual(to: other.native)
  }

  @_transparent
  public func isLess(than other: CGFloat) -> Bool {
    return self.native.isLess(than: other.native)
  }

  @_transparent
  public func isLessThanOrEqualTo(_ other: CGFloat) -> Bool {
    return self.native.isLessThanOrEqualTo(other.native)
  }

  @_transparent
  public var isNormal:  Bool {
    return native.isNormal
  }

  @_transparent
  public var isFinite:  Bool {
    return native.isFinite
  }

  @_transparent
  public var isZero:  Bool {
    return native.isZero
  }

  @_transparent
  public var isSubnormal:  Bool {
    return native.isSubnormal
  }

  @_transparent
  public var isInfinite:  Bool {
    return native.isInfinite
  }

  @_transparent
  public var isNaN:  Bool {
    return native.isNaN
  }

  @_transparent
  public var isSignalingNaN: Bool {
    return native.isSignalingNaN
  }

  @available(*, unavailable, renamed: "isSignalingNaN")
  public var isSignaling: Bool {
    fatalError("unavailable")
  }

  @_transparent
  public var isCanonical: Bool {
    return true
  }

  @_transparent
  public var floatingPointClass: FloatingPointClassification {
    return native.floatingPointClass
  }

  @_transparent
  public var binade: CGFloat {
    return CGFloat(native.binade)
  }

  @_transparent
  public var significandWidth: Int {
    return native.significandWidth
  }

  /// Create an instance initialized to `value`.
  @_transparent
  public init(floatLiteral value: NativeType) {
    native = value
  }

  /// Create an instance initialized to `value`.
  @_transparent
  public init(integerLiteral value: Int) {
    native = NativeType(value)
  }
}

extension CGFloat {
  @available(*, unavailable, renamed: "leastNormalMagnitude")
  public static var min: CGFloat {
    fatalError("unavailable")
  }

  @available(*, unavailable, renamed: "greatestFiniteMagnitude")
  public static var max: CGFloat {
    fatalError("unavailable")
  }
}

@available(*, unavailable, renamed: "CGFloat.leastNormalMagnitude")
public var CGFLOAT_MIN: CGFloat {
  fatalError("unavailable")
}

@available(*, unavailable, renamed: "CGFloat.greatestFiniteMagnitude")
public var CGFLOAT_MAX: CGFloat {
  fatalError("unavailable")
}

extension CGFloat : CustomReflectable {
  /// Returns a mirror that reflects `self`.
  public var customMirror: Mirror {
    return Mirror(reflecting: native)
  }
}

extension CGFloat : CustomStringConvertible {
  /// A textual representation of `self`.
  @_transparent
  public var description: String {
    return native.description
  }
}

extension CGFloat : Hashable {
  /// The hash value.
  ///
  /// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`
  ///
  /// - Note: the hash value is not guaranteed to be stable across
  ///   different invocations of the same program.  Do not persist the
  ///   hash value across program runs.
  @_transparent
  public var hashValue: Int {
    return native.hashValue
  }

  /// Hashes the essential components of this value by feeding them into the
  /// given hasher.
  ///
  /// - Parameter hasher: The hasher to use when combining the components
  ///   of this instance.
  @inlinable @_transparent
  public func hash(into hasher: inout Hasher) {
    hasher.combine(native)
  }

  @_alwaysEmitIntoClient @inlinable // Introduced in 5.1
  public func _rawHashValue(seed: Int) -> Int {
    return native._rawHashValue(seed: seed)
  }
}

% for dst_ty in all_integer_types(word_bits):

extension ${dst_ty.stdlib_name} {
  @_transparent
  public init(_ value: CGFloat) {
    self = ${dst_ty.stdlib_name}(value.native)
  }
}

% end


extension Double {
  @_transparent
  public init(_ value: CGFloat) {
    self = Double(value.native)
  }
}

extension Float {
  @_transparent
  public init(_ value: CGFloat) {
    self = Float(value.native)
  }
}

//===----------------------------------------------------------------------===//
// Standard Operator Table
//===----------------------------------------------------------------------===//

//  TODO: These should not be necessary, since they're already provided by
//  <T: FloatingPoint>, but in practice they are currently needed to
//  disambiguate overloads.  We should find a way to remove them, either by
//  tweaking the overload resolution rules, or by removing the other
//  definitions in the standard lib, or both.

extension CGFloat {
  @_transparent
  public static func +(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
    var lhs = lhs
    lhs += rhs
    return lhs
  }

  @_transparent
  public static func -(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
    var lhs = lhs
    lhs -= rhs
    return lhs
  }

  @_transparent
  public static func *(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
    var lhs = lhs
    lhs *= rhs
    return lhs
  }

  @_transparent
  public static func /(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
    var lhs = lhs
    lhs /= rhs
    return lhs
  }
}

//===----------------------------------------------------------------------===//
// Strideable Conformance
//===----------------------------------------------------------------------===//

extension CGFloat : Strideable {
  /// Returns a stride `x` such that `self.advanced(by: x)` approximates
  /// `other`.
  ///
  /// - Complexity: O(1).
  @_transparent
  public func distance(to other: CGFloat) -> CGFloat {
    return CGFloat(other.native - self.native)
  }

  /// Returns a `Self` `x` such that `self.distance(to: x)` approximates
  /// `n`.
  ///
  /// - Complexity: O(1).
  @_transparent
  public func advanced(by amount: CGFloat) -> CGFloat {
    return CGFloat(self.native + amount.native)
  }
}

//===----------------------------------------------------------------------===//
// Deprecated operators
//===----------------------------------------------------------------------===//

@_transparent
@available(*, unavailable, message: "Use truncatingRemainder instead")
public func %(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
  fatalError("% is not available.")
}

@_transparent
@available(*, unavailable, message: "Use formTruncatingRemainder instead")
public func %=(lhs: inout CGFloat, rhs: CGFloat) {
  fatalError("%= is not available.")
}

//===----------------------------------------------------------------------===//
// tgmath
//===----------------------------------------------------------------------===//

%{
UnaryFunctions = [
  'acos', 'asin', 'atan', 'cos', 'sin', 'tan',
  'acosh', 'asinh', 'atanh', 'cosh', 'sinh', 'tanh',
  'exp', 'exp2', 'expm1',
  'log', 'log10', 'log1p', 'log2', 'logb',
  'cbrt', 'erf', 'erfc', 'tgamma',
  'nearbyint', 'rint'
]

BinaryFunctions = [
  'atan2', 'hypot', 'pow', 'copysign', 'nextafter', 'fdim', 'fmax', 'fmin'
]
}%

%for ufunc in UnaryFunctions:
@_transparent
public func ${ufunc}(_ x: CGFloat) -> CGFloat {
  return CGFloat(${ufunc}(x.native))
}

%end

%for bfunc in BinaryFunctions:
@_transparent
public func ${bfunc}(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat {
  return CGFloat(${bfunc}(lhs.native, rhs.native))
}

%end

@_transparent
@available(*, unavailable, message: "use the floatingPointClass property.")
public func fpclassify(_ x: CGFloat) -> Int {
  fatalError("unavailable")
}

@available(*, unavailable, message: "use the isNormal property.")
public func isnormal(_ value: CGFloat) -> Bool { return value.isNormal }

@available(*, unavailable, message: "use the isFinite property.")
public func isfinite(_ value: CGFloat) -> Bool { return value.isFinite }

@available(*, unavailable, message: "use the isInfinite property.")
public func isinf(_ value: CGFloat) -> Bool { return value.isInfinite }

@available(*, unavailable, message: "use the isNaN property.")
public func isnan(_ value: CGFloat) -> Bool { return value.isNaN }

@available(*, unavailable, message: "use the sign property.")
public func signbit(_ value: CGFloat) -> Int { return value.sign.rawValue }

@available(swift, deprecated: 4.2, renamed: "scalbn")
@_transparent
public func ldexp(_ x: CGFloat, _ n: Int) -> CGFloat {
  return CGFloat(ldexp(x.native, n))
}

@available(swift, deprecated: 4.2, message: "use the exponent property.")
@_transparent
public func ilogb(_ x: CGFloat) -> Int {
  return Int(x.exponent)
}

@_transparent
public func lgamma(_ x: CGFloat) -> (CGFloat, Int) {
  let (value, sign) = lgamma(x.native)
  return (CGFloat(value), sign)
}

@_transparent
public func remquo(_ x: CGFloat, _ y: CGFloat) -> (CGFloat, Int) {
  let (rem, quo) = remquo(x.native, y.native)
  return (CGFloat(rem), quo)
}

@available(swift, deprecated: 4.2, message:
           "use CGFloat(nan: CGFloat.RawSignificand) instead.")
@_transparent
public func nan(_ tag: String) -> CGFloat {
  return CGFloat(nan(tag) as CGFloat.NativeType)
}

@_transparent
public func j0(_ x: CGFloat) -> CGFloat {
  return CGFloat(j0(Double(x.native)))
}

@_transparent
public func j1(_ x: CGFloat) -> CGFloat {
  return CGFloat(j1(Double(x.native)))
}

@_transparent
public func jn(_ n: Int, _ x: CGFloat) -> CGFloat {
  return CGFloat(jn(n, Double(x.native)))
}

@_transparent
public func y0(_ x: CGFloat) -> CGFloat {
  return CGFloat(y0(Double(x.native)))
}

@_transparent
public func y1(_ x: CGFloat) -> CGFloat {
  return CGFloat(y1(Double(x.native)))
}

@_transparent
public func yn(_ n: Int, _ x: CGFloat) -> CGFloat {
  return CGFloat(yn(n, Double(x.native)))
}

extension CGFloat : _CVarArgPassedAsDouble, _CVarArgAligned {
  /// Transform `self` into a series of machine words that can be
  /// appropriately interpreted by C varargs
  @_transparent
  public var _cVarArgEncoding: [Int] {
    return native._cVarArgEncoding
  }

  /// Return the required alignment in bytes of
  /// the value returned by `_cVarArgEncoding`.
  @_transparent
  public var _cVarArgAlignment: Int {
    return native._cVarArgAlignment
  }
}

extension CGFloat : Codable {
  @_transparent
  public init(from decoder: Decoder) throws {
    let container = try decoder.singleValueContainer()
    do {
      self.native = try container.decode(NativeType.self)
    } catch DecodingError.typeMismatch(let type, let context) {
      // We may have encoded as a different type on a different platform. A
      // strict fixed-format decoder may disallow a conversion, so let's try the
      // other type.
      do {
        if NativeType.self == Float.self {
          self.native = NativeType(try container.decode(Double.self))
        } else {
          self.native = NativeType(try container.decode(Float.self))
        }
      } catch {
        // Failed to decode as the other type, too. This is neither a Float nor
        // a Double. Throw the old error; we don't want to clobber the original
        // info.
        throw DecodingError.typeMismatch(type, context)
      }
    }
  }

  @_transparent
  public func encode(to encoder: Encoder) throws {
    var container = encoder.singleValueContainer()
    try container.encode(self.native)
  }
}
